﻿using System;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Windows.Forms;

using OrderAggregator.Core;
using OrderAggregator.DataStorage;
using OrderAggregator.InputFormats;

namespace OrderAggregator.UI
{
    public partial class MainForm : Form
    {
        private readonly Timer _timer = new Timer();

        private readonly OrderAggregator.Core.Aggregator _aggregator;

        private readonly DataStorage.Storage _storage = CreateStorage();

        private bool _inTick = false;

        public MainForm()
        {
            InitializeComponent();

            this.Icon = UIManager.GetIcon("App.ico");

            InitTablesMenu();
            
            var aggrConfig = new AggregatorConfig();
            aggrConfig.Load(
                System.IO.Path.Combine(
                System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location),
                "OrderAggregator.config"
                )
                );


            if (File.Exists(StoragePath))
            {
                _storage.ReadXml(StoragePath);
                _storage.AcceptChanges();
            }

            _aggregator = new Aggregator(
                aggrConfig, 
                _storage,
                ResolveProduct,
                ResolveOrganization
                );

            _timer.Interval = 2000;
            _timer.Tick += OnTimer_Tick;

            mnuAbout.Click += delegate { OnAbout(); };
        }

       

        private void OnTimer_Tick(object sender, EventArgs e)
        {
            if (_inTick)
            {
                return;
            }

            _inTick = true;

            try
            {
                _aggregator.Do();

                lblOrderCount.Text = _aggregator.ProcessedOrders.ToString();
            }
            catch (Exception ex)
            {
                StopTimer();

                LogError(ex);

                MessageBox.Show(
                    ex.Message,
                    "Ошибка агрегации:",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error
                    );
            }
            finally
            {
                _inTick = false;
            }

        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            StartTimer();
        }

        private static string StoragePath
        {
            get
            {
                return Path.Combine(WorkDirectoryPath, "Data\\Storage.xml");
                
            }
        }

        private static string WorkDirectoryPath
        {
            get
            {
                return Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location);
            }
        }

        private static Storage CreateStorage()
        {
            Storage storage = new Storage();
            
            return storage;
        }

        /// <summary>
        /// Иниц. меню Справочники
        /// </summary>
        private void InitTablesMenu()
        {
            foreach (System.Data.DataTable table in _storage.Tables)
            {
                var item = new ToolStripMenuItem(UIManager.GetTableTitle(table));
                item.Tag = table.TableName;
                item.Click += menuItem_Click;

                this.mnuСправочники.DropDownItems.Add(item);
            }
        }

        private void menuItem_Click(object sender, EventArgs e)
        {
            var item = (ToolStripMenuItem) sender;

            var tableName = (string) item.Tag;
            System.Data.DataTable table = _storage.Tables[tableName];

            EditTable(table);
        }

        private Storage.ProductRow ResolveProduct(Storage.OrganizationRow organization, BaseOrderRow orderRow)
        {
            var productResControl = new ProductResolveControl();
            productResControl.Init(organization, orderRow);

            using (var editDialog = new EditDialog())
            {
                editDialog.Text = "Разрешение неизвестной позиции заказа:";
                editDialog.Icon = UIManager.GetIcon("Warning.ico");
                editDialog.HostedControl = productResControl;


                if (editDialog.ShowDialog() != DialogResult.OK)
                {
                    return null;
                }

                var product = productResControl.Product;
                organization = productResControl.Organization;

                if (product == null)
                {
                    return null;
                }

                var relations = ((Storage)organization.Table.DataSet).OrganizationProductRelation;

                var productRef = relations.NewOrganizationProductRelationRow();
                productRef.OrganizationRow = organization;
                productRef.ProductRow = product;
                productRef.ProductCode = orderRow.ProductCode;

                relations.AddOrganizationProductRelationRow(productRef);

                _storage.AcceptChanges();
                _storage.WriteXml(StoragePath);

                return product;
            }
        }

        private Storage.OrganizationRow ResolveOrganization(Storage storage, BaseOrder order)
        {
            var orgResControl = new OrganizationResolveControl();
            orgResControl.Init(storage, order);

            using (var editDialog = new EditDialog())
            {
                editDialog.Text = "Разрешение неизвестной организации:";
                editDialog.Icon = UIManager.GetIcon("Warning.ico");
                editDialog.HostedControl = orgResControl;

                if (editDialog.ShowDialog() != DialogResult.OK)
                {
                    return null;
                }

                Storage.OrganizationRow organization = orgResControl.SelectedOrganization;

                if (!orgResControl.UseExistintOrg || organization == null)
                {
                    organization = storage.Organization.NewOrganizationRow();
                    organization.Name = order.Client;
                    organization.OrganizationRowParent = orgResControl.SelectedOrganization;
                    storage.Organization.AddOrganizationRow(organization);
                }
                else
                {
                    organization.Name = order.Client;
                }

                _storage.AcceptChanges();
                _storage.WriteXml(StoragePath);

                return organization;
            }
        }

        private void EditTable(System.Data.DataTable table)
        {
            var editControl = UIManager.CreateListControl(table);
            
            using (var editDialog = new EditDialog())
            {
                LoadEditDialogState(editDialog);

                editDialog.Text = "Справочник: " + UIManager.GetTableTitle(table);
                editDialog.HostedControl = editControl;

                var editRes = editDialog.ShowDialog();

                SaveEditDialogState(editDialog);

                if (editRes == DialogResult.OK)
                {
                    _storage.AcceptChanges();
                    _storage.WriteXml(StoragePath);
                    return;
                }
            }

            _storage.RejectChanges();
            
        }

        private void btnStartStop_Click(object sender, EventArgs e)
        {
            if (!_timer.Enabled)
            {
                StartTimer();
            }
            else
            {
                StopTimer();
            }
        }

        private void StartTimer()
        {
            _aggregator.PreDo();

            _timer.Enabled = true;
            _timer.Start();

            btnStartStop.Text = "Остановить";
            mnuСправочники.Enabled = false;
        }

        private void StopTimer()
        {
            _timer.Enabled = false;
            _timer.Stop();

            btnStartStop.Text = "Запустить";
            mnuСправочники.Enabled = true;

            lblOrderCount.Text = _aggregator.ProcessedOrders.ToString();
        }

        private static void LogError(Exception ex)
        {
            try
            {
                var logFile = Path.Combine(WorkDirectoryPath, "Errors.log");

                string errorText = DateTime.Now.ToString();
                errorText += System.Environment.NewLine;
                errorText += ex.ToString();
                errorText += System.Environment.NewLine;
                errorText += System.Environment.NewLine;

                File.AppendAllText(logFile, errorText);
            }
            catch
            {
                //nothing
            }
        }

        private object[] _editDialogState = null;

        private void SaveEditDialogState(EditDialog editDialog)
        {
            _editDialogState = new object[]
                                   {
                                       editDialog.Size,
                                       editDialog.WindowState
                                   };
        }

        private void LoadEditDialogState(EditDialog editDialog)
        {
            if (_editDialogState == null)
            {
                return;
            }

            editDialog.Size = (Size)_editDialogState[0];
            editDialog.WindowState = (FormWindowState)_editDialogState[1];
        }

        private static void OnAbout()
        {
            using (var abot = new About())
            {
                abot.ShowDialog();
            }
        }
    }
}
